<template>
  <transition name="v-message-box-fade">
    <div
      v-show="visible"
      class="v-message-box_wrapper"
      @click.self="handleWrapperClick"
    >
      <div class="v-message-box">
        <div class="v-message-box_header">
          <div class="v-message-box_title">
            <i :class="['v-message-box_icon', 'v-icon_' + type]"></i>
            <span>{{ title }}</span>
          </div>
          <i
            v-if="showClose"
            class="v-message-box_icon v-icon_close"
            @click="handleAction('close')"
          ></i>
        </div>
        <div class="v-message-box_message">
          <p v-if="!dangerouslyUseHTMLString">{{ message }}</p>
          <p v-else v-html="message"></p>
        </div>
        <div class="v-message-box_btns">
          <button
            v-if="showCancelButton"
            class="v-btns_cancel"
            @click="handleAction('cancel')"
          >
            {{ cancelButtonText || "取消" }}
          </button>
          <button
            v-if="showConfirmButton"
            class="v-btns_confirm"
            @click="handleAction('confirm')"
          >
            {{ confirmButtonText || "确定" }}
          </button>
        </div>
      </div>
    </div>
  </transition>
</template>
<script>
export default {
  data() {
    return {
      visible: false,
      title: "",
      message: "",
      dangerouslyUseHTMLString: false,
      type: "info",
      callback: null,
      showClose: true,
      beforeClose: null,
      lockScroll: false,
      showCancelButton: true,
      showConfirmButton: true,
      cancelButtonText: "取消",
      confirmButtonText: "确定",
      closeOnClickModal: true,
      closeOnPressEscape: true,
      closeOnHashChange: true,
      distinguishCancelAndClose: true,
    };
  },
  created() {},
  mounted() {
    this.$nextTick(() => {
      if (this.closeOnHashChange) {
        window.addEventListener("hashchange", () => this.handleWrapperClick());
      }
      if (this.closeOnPressEscape) {
        window.addEventListener("keyup", (e) => {
          if (e.key == "Escape") {
            this.handleWrapperClick();
          }
        });
      }
    });
  },
  methods: {
    handleWrapperClick() {
      if (this.closeOnClickModal) {
        this.handleAction(this.distinguishCancelAndClose ? "close" : "cancel");
      }
    },
    getSafeClose() {
      const currentId = this.uid;
      return () => {
        this.$nextTick(() => {
          if (currentId === this.uid) this.doClose();
        });
      };
    },
    doClose() {
      if (!this.visible) return;
      this.visible = false;
      this._closing = true;

      this.onClose && this.onClose();
      if (this.lockScroll) {
        document.body.style = {};
      }
      setTimeout(() => {
        if (this.action) this.callback(this.action, this);
      });
    },
    handleAction(action) {
      if (this.$type === "prompt" && action === "confirm" && !this.validate()) {
        return;
      }
      this.action = action;
      if (typeof this.beforeClose === "function") {
        this.close = this.getSafeClose();
        this.beforeClose(action, this, this.close);
      } else {
        this.doClose();
      }
    },
  },
  beforeDestroy() {
    const _this = this;
    if (this.closeOnHashChange) {
      window.removeEventListener("hashchange", _this.close);
    }
    if (this.closeOnPressEscape) {
      window.removeEventListener("keyup", _this.handleWrapperClick);
    }
  },
};
</script>
<style lang="less" scoped>
.v-message-box_wrapper {
  position: fixed;
  top: -20px;
  left: -20px;
  right: -20px;
  bottom: -20px;
  text-align: center;
  z-index: 1000;
  background-color: rgba(0, 0, 0, 0.5);
  transition: all 0.3s;
  &::after {
    content: "";
    display: inline-block;
    height: 100%;
    width: 0;
    vertical-align: middle;
  }
}
.v-message-box {
  display: inline-block;
  vertical-align: middle;
  width: 360px;
  padding: 15px;
  text-align: left;
  background-color: #fff;
  border-radius: 6px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  .v-message-box_header {
    position: relative;
    .v-message-box_title {
      display: flex;
      align-items: center;
    }
    .v-message-box_icon {
      position: relative;
      width: 20px;
      height: 20px;
      margin-right: 5px;
      background-size: contain;
      background-repeat: no-repeat;
      &.v-icon_info {
        background-image: url("./icon/info.png");
      }
      &.v-icon_error {
        background-image: url("./icon/error.png");
      }
      &.v-icon_warning {
        background-image: url("./icon/warning.png");
      }
      &.v-icon_success {
        background-image: url("./icon/success.png");
      }
      &.v-icon_close {
        position: absolute;
        top: 50%;
        right: 0;
        transform: translateY(-50%);
        cursor: pointer;
        margin-right: 0;
        &::before,
        &::after {
          position: absolute;
          top: 50%;
          left: 50%;
          content: "";
          display: block;
          width: 70%;
          height: 1px;
          background: #666;
        }
        &::before {
          transform: translate(-50%, -50%) rotate(45deg);
        }
        &::after {
          transform: translate(-50%, -50%) rotate(-45deg);
        }
      }
    }
  }
  .v-message-box_message {
    padding: 10px 0;
  }
  .v-message-box_btns {
    display: flex;
    justify-content: flex-end;
    .v-btns_cancel {
      border: 1px solid #ddd;
    }
    .v-btns_confirm {
      margin-left: 10px;
      color: #fff;
      border: 1px solid #ff5858;
      background-color: #ff5858;
    }
  }
}

.v-message-box-fade-enter,.v-message-box-fade-leave-active{
  opacity: 0;
  transform: translateY(-20px);
}
</style>
